from . import question_blueprint
from ..utils.response_util import *
from ..utils.exception import APIException
from ..utils.error_code import *
from ..utils.check import *
from ..models import *
from config import oj_url, TARGET_PATH
from ..utils.question_utils import *

from flask import request, session
import json
from sqlalchemy.sql import func
import random
import requests
from math import ceil
import os
import shutil


@question_blueprint.route("/", methods=["GET", "POST"])
def question_main():
    return "Question"


@question_blueprint.errorhandler(APIException)
def question_error(e):
    return APIException.to_dict(e)


def get_file_num(filename):
    l_index = filename.find(".")
    s_index = filename.find("#")
    return filename[s_index+1: l_index]


@question_blueprint.route("/list", methods=["POST"])
def question_list():
    """
    用户可见的所有问题列表
    :return:
    """
    data = get_data()
    try:
        current_page = int(request.args.get("currentPage"))
    except:
        current_page = 1
    data_per_page = 10

    username = session.get("username")
    r = list()

    if username is not None:
        user = User.query.filter_by(username=username).limit(1).first()
        if user is not None:
            if user.user_type > 1:
                questions = Question.query.all()
            elif user.user_type == 1:
                questions = Question.query.filter_by(status=True).all()
        else:
            raise APIException(USERNAME_NOT_EXISTS)
    else:
        questions = Question.query.filter_by(status=True).all()

    list_len = len(questions)
    for question in questions:
        tmp = dict()
        real_question = None
        question_id = question.question_id
        real_question, question_type = get_real_question(question_id)
        if real_question is None:
            continue

        sql = "SELECT count(*) FROM `user_submit` WHERE status=TRUE AND question_id=" + str(question_id)
        right_submits = db.session.execute(sql).scalar()
        sql = "SELECT count(*) FROM `user_submit` WHERE status=TRUE AND result=100 AND question_id=" + str(question_id)
        all_submits = db.session.execute(sql).scalar()
        tmp["questionId"] = real_question.question_id
        tmp["questionTitle"] = real_question.question_title
        tmp["questionDifficulty"] = real_question.question_difficulty
        tmp["questionCreateTime"] = str(real_question.create_time)
        tmp["questionType"] = get_type(question_type)

        if all_submits != 0:
            tmp["passPercent"] = right_submits / all_submits
        else:
            tmp["passPercent"] = 0
        r.append(tmp)

    max_page_num = ceil(list_len / data_per_page)

    ret = {
        "currentPage": current_page,
        "maxPageNum": max_page_num,
        "num": list_len,
        "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
    }

    return response(601, "Query Question List Success", ret)


@question_blueprint.route("/search", methods=["GET"])
def question_search():
    """
    查看问题
    :return:
    """
    data = request.args
    question_id = data.get("questionId")
    r = dict()

    tmp_question = Question.query.filter_by(question_id=question_id).first()
    if tmp_question is None:
        raise APIException(NO_QUESTION_EXISTS)
    question_type = tmp_question.question_type
    # 填空题
    if question_type == 1:
        question = QuestionOfFillBlank.query.filter_by(question_id=question_id).first()
    # 选择题
    elif question_type == 2:
        question = QuestionOfSelect.query.filter_by(question_id=question_id).first()
        l = json.loads(question.wrong_answer)
        l.append(question.right_answer)
        random.shuffle(l)
        r["options"] = l
    # 判断题
    elif question_type == 3:
        question = QuestionOfJudge.query.filter_by(question_id=question_id).first()
    # 程序填空题
    elif question_type == 4:
        question = QuestionOfProgramFillBlank.query.filter_by(question_id=question_id).first()
        r["inputFormat"] = question.input_format[: 3]
        r["outputFormat"] = question.output_format[: 3]
    # 程序改错题
    elif question_type == 5:
        question = QuestionOfProgramModify.query.filter_by(question_id=question_id).first()
        r["inputFormat"] = question.input_format[: 3]
        r["outputFormat"] = question.output_format[: 3]
    # 编程题
    elif question_type == 6:
        question = QuestionOfProgram.query.filter_by(question_id=question_id).first()
        r["inputFormat"] = question.input_format[: 3]
        r["outputFormat"] = question.output_format[: 3]

    r["questionType"] = get_type(question_type)
    r["questionTitle"] = question.question_title
    r["relateCourse"] = question.relate_course_id
    r["questionDifficulty"] = question.question_difficulty
    r["questionDescription"] = question.question_description
    r["createTime"] = str(question.create_time)

    return response(619, "Search Question Success", r)


@question_blueprint.route("/add/fill-blank", methods=["POST"])
@user_is_login
@check_user_type_2
def question_of_fill_blank_add():
    """
    添加填空题
    :return:
    """
    data = get_data()
    problem_title = data.get("questionTitle")
    relate_course = data.get("relateCourse")
    relate_chapter = data.get("relateChapter")
    problem_difficulty = data.get("questionDifficulty")
    problem_description = data.get("questionDescription")
    problem_answer = data.get("questionAnswer")
    relate_knowledge = data.get("relateKnowledge")
    score = data.get("score")
    username = session.get("username")

    question = Question(1, score, relate_chapter, json.dumps(relate_knowledge), username)
    db.session.add(question)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    question_id = question.question_id
    question_of_fill_blank = QuestionOfFillBlank(
        question_id,
        problem_title,
        relate_course,
        problem_difficulty,
        json.dumps(problem_description, ensure_ascii=False),
        json.dumps(problem_answer, ensure_ascii=False)
    )
    try:
        db.session.add(question_of_fill_blank)
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    return response(200, "Add Question Of Fill Blank Success", {"questionID": question_id})

@question_blueprint.route("/add/select", methods=["POST"])
@user_is_login
@check_user_type_2
def question_of_select_add():
    """
    添加选择题
    :return:
    """
    data = get_data()
    question_title = data.get("questionTitle")
    relate_chapter = data.get("relateChapter")
    relate_course = data.get("relateCourse")
    relate_knowledge = data.get("relateKnowledge")
    question_difficulty = data.get("questionDifficulty")
    question_description = data.get("questionDescription")
    wrong_answer = data.get("wrongAnswer")
    right_answer = data.get("rightAnswer")
    score = data.get("score")
    username = session.get("username")

    question = Question(2, score, relate_chapter, json.dumps(relate_knowledge), username)
    db.session.add(question)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    question_id = question.question_id

    question_of_select = QuestionOfSelect(
        question_id,
        question_title,
        relate_course,
        question_difficulty,
        json.dumps(question_description, ensure_ascii=False),
        json.dumps(wrong_answer, ensure_ascii=False),
        right_answer
    )
    db.session.add(question_of_select)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    return response(200, "Add Select Success", {"questionID": question_id})


@question_blueprint.route("/add/judge", methods=["POST"])
@user_is_login
@check_user_type_2
def question_of_judge_add():
    """
    添加判断题
    :return:
    """
    data = get_data()
    question_title = data.get("questionTitle")
    relate_chapter = data.get("relateChapter")
    relate_course = data.get("relateCourse")
    relate_knowledge = data.get("relateKnowledge")
    question_difficulty = data.get("questionDifficulty")
    question_description = data.get("questionDescription")
    right_answer = data.get("rightAnswer")
    score = data.get("score")
    username = session.get("username")

    question = Question(3, score, relate_chapter, json.dumps(relate_knowledge), username)
    db.session.add(question)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    question_id = question.question_id

    question_of_judge = QuestionOfJudge(question_id, question_title, relate_course, question_difficulty,
                                          json.dumps(question_description, ensure_ascii=False), right_answer)
    db.session.add(question_of_judge)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    return response(200, "Add Judge Success", {"questionID": question_id})


@question_blueprint.route("/add/program-fill-blank", methods=["POST"], endpoint="questionOfSelectAdd")
@user_is_login
@check_user_type_2
def question_of_select_add():
    """
    添加程序填空题
    :return:
    """
    data = get_data()
    problem_title = data.get("questionTitle")
    relate_chapter = data.get("relateChapter")
    relate_course = data.get("relateCourse")
    problem_difficulty = data.get("questionDifficulty")
    problem_description = data.get("questionDescription")
    question_answer = data.get("questionAnswer")
    relate_knowledge = data.get("relateKnowledge")
    input_format = data.get("inputFormat")
    output_format = data.get("outputFormat")
    keyword = data.get("keyword")
    score = data.get("score")
    username = session.get("username")
    # 获得输入输出指定格式文件
    input_files = request.files.getlist("input_file")
    output_files = request.files.getlist("output_file")

    question = Question(4, score, relate_chapter, json.dumps(relate_knowledge, ensure_ascii=False), username)
    db.session.add(question)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    question_id = question.question_id

    question_of_program_fill_blank = QuestionOfProgramFillBlank(
        question_id,
        problem_title,
        relate_course,
        problem_difficulty,
        problem_description,
        json.dumps(question_answer, ensure_ascii=False),
        json.dumps(input_format, ensure_ascii=False),
        json.dumps(output_format, ensure_ascii=False),
        json.dumps(keyword, ensure_ascii=False)
    )
    db.session.add(question_of_program_fill_blank)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)

    # test_point_list = list()
    # test_point_data = dict()
    # for input_data in input_format:
    #     test_point_number = input_data["num"]
    #     input_content = input_data["content"]
    #     test_point_data[test_point_number] = dict()
    #     test_point_data[test_point_number]["input"] = " ".join('%s' % content for content in input_content)
    # for output_data in output_format:
    #     test_point_number = output_data["num"]
    #     output_content = output_data["content"]
    #     test_point_data[test_point_number]["output"] = " ".join('%s' % content for content in output_content)
    #
    # for i, input_and_output in test_point_data.items():
    #     test_point = QuestionTestPoint(1, i, question_id, input_and_output["input"], input_and_output["output"], score)
    #     test_point_list.append(test_point)
    test_point_list = list()
    for input_file, output_file in zip(input_files, output_files):
        if input_file and allowed_file(input_file.filename):
            join_path = os.path.join(TARGET_PATH, str(username), get_file_num(input_file.filename))
            my_input_path = os.path.join(join_path, "input")
            if not os.path.exists(my_input_path):
                os.makedirs(my_input_path)
            input_file.save(os.path.join(my_input_path, input_file.filename))
        if output_file and allowed_file(output_file.filename):
            my_output_path = os.path.join(join_path, "output")
            if not os.path.exists(my_output_path):
                os.makedirs(my_output_path)
            output_file.save(os.path.join(my_output_path, output_file.filename))
        input_path = str(os.path.join(os.path.abspath(my_input_path), input_file.filename))
        output_path = str(os.path.join(os.path.abspath(my_output_path), output_file.filename))
        test_point = QuestionTestPoint(0,
                                       get_file_num(input_file.filename),
                                       question_id,
                                       input_path,
                                       output_path,
                                       score)
        test_point_list.append(test_point)
    try:
        db.session.add_all(test_point_list)
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    return response(200, "Add Question Of Program Fill Blank Success", {"questionID": question_id})


@question_blueprint.route("/add/program-modify", methods=["POST"])
@user_is_login
@check_user_type_2
def question_of_program_modify_add():
    """
    添加程序改错题
    :return:
    """
    data = get_data()
    question_title = data.get("questionTitle")
    relate_chapter = data.get("relateChapter")
    relate_course = data.get("relateCourse")
    question_difficulty = data.get("questionDifficulty")
    question_description = data.get("questionDescription")
    question_answer = data.get("questionAnswer")
    input_format = data.get("inputFormat")
    relate_knowledge = data.get("relateKnowledge")
    output_format = data.get("outputFormat")
    keyword = data.get("keyword")
    score = data.get("score")
    username = session.get("username")
    # 获得输入输出指定格式文件
    input_files = request.files.getlist("input_file")
    output_files = request.files.getlist("output_file")

    question = Question(5, score, relate_chapter, json.dumps(relate_knowledge, ensure_ascii=False), username)
    db.session.add(question)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    question_id = question.question_id

    question_of_program_modify = QuestionOfProgramModify(
        question_id,
        question_title,
        relate_course,
        question_difficulty,
        json.dumps(question_description, ensure_ascii=False),
        json.dumps(question_answer, ensure_ascii=False),
        json.dumps(input_format, ensure_ascii=False),
        json.dumps(output_format, ensure_ascii=False),
        json.dumps(keyword, ensure_ascii=False)
    )
    db.session.add(question_of_program_modify)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)

    # test_point_list = list()
    # test_point_data = dict()
    # for input_data in input_format:
    #     test_point_number = input_data["num"]
    #     input_content = input_data["content"]
    #     test_point_data[test_point_number] = dict()
    #     test_point_data[test_point_number]["input"] = " ".join('%s' % content for content in input_content)
    # for output_data in output_format:
    #     test_point_number = output_data["num"]
    #     output_content = output_data["content"]
    #     test_point_data[test_point_number]["output"] = " ".join('%s' % content for content in output_content)
    #
    # for i, input_and_output in test_point_data.items():
    #     test_point = QuestionTestPoint(1, i, question_id, input_and_output["input"], input_and_output["output"], score)
    #     test_point_list.append(test_point)
    test_point_list = list()
    for input_file, output_file in zip(input_files, output_files):
        if input_file and allowed_file(input_file.filename):
            join_path = os.path.join(TARGET_PATH, str(username), get_file_num(input_file.filename))
            my_input_path = os.path.join(join_path, "input")
            if not os.path.exists(my_input_path):
                os.makedirs(my_input_path)
            input_file.save(os.path.join(my_input_path, input_file.filename))
        if output_file and allowed_file(output_file.filename):
            my_output_path = os.path.join(join_path, "output")
            if not os.path.exists(my_output_path):
                os.makedirs(my_output_path)
            output_file.save(os.path.join(my_output_path, output_file.filename))
        input_path = str(os.path.join(os.path.abspath(my_input_path), input_file.filename))
        output_path = str(os.path.join(os.path.abspath(my_output_path), output_file.filename))
        test_point = QuestionTestPoint(0,
                                       get_file_num(input_file.filename),
                                       question_id,
                                       input_path,
                                       output_path,
                                       score)
        test_point_list.append(test_point)
    try:
        db.session.add_all(test_point_list)
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    return response(200, "Add Question Of Program Fill Blank Success", {"questionID": question_id})


@question_blueprint.route("/add/program", methods=["POST"])
@user_is_login
@check_user_type_2
def question_of_program_add():
    """
    添加编程题
    :return:
    """
    data = get_data()
    question_title = data.get("questionTitle")
    relate_course = data.get("relateCourse")
    relate_chapter = data.get("relateChapter")
    question_difficulty = data.get("questionDifficulty")
    question_description = data.get("questionDescription")
    input_sample_format = data.get("inputSampleFormat")
    output_sample_format = data.get("outputSampleFormat")
    score = data.get("score")
    relate_knowledge = data.get("relateKnowledge")
    keyword = data.get("keyword")
    username = session.get("username")
    # 获得输入输出指定格式文件
    input_files = request.files.getlist("input_file")
    output_files = request.files.getlist("output_file")

    question = Question(6, score, relate_chapter, json.dumps(relate_knowledge, ensure_ascii=False), username)
    db.session.add(question)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    question_id = question.question_id

    question_of_program = QuestionOfProgram(
        question_id,
        question_title,
        relate_course,
        question_difficulty,
        question_description,
        json.dumps(input_sample_format, ensure_ascii=False),
        json.dumps(output_sample_format, ensure_ascii=False),
        json.dumps(keyword, ensure_ascii=False)
    )
    db.session.add(question_of_program)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)

    # 数据库型
    # test_point_list = list()
    # test_point_data = dict()
    # for input_data in input_format:
    #     test_point_number = input_data["num"]
    #     input_content = input_data["content"]
    #     test_point_data[test_point_number] = dict()
    #     test_point_data[test_point_number]["input"] = " ".join('%s' %content for content in input_content)
    # for output_data in output_format:
    #     test_point_number = output_data["num"]
    #     output_content = output_data["content"]
    #     test_point_data[test_point_number]["output"] = " ".join('%s' %content for content in output_content)
    #
    # for i, input_and_output in test_point_data.items():
    #     test_point = QuestionTestPoint(1, i, question_id, input_and_output["input"], input_and_output["output"], score)
    #     test_point_list.append(test_point)

    # 文件型
    test_point_list = list()
    for input_file, output_file in zip(input_files, output_files):
        if input_file and allowed_file(input_file.filename):
            join_path = os.path.join(TARGET_PATH, str(username), get_file_num(input_file.filename))
            my_input_path = os.path.join(join_path, "input")
            if not os.path.exists(my_input_path):
                os.makedirs(my_input_path)
            input_file.save(os.path.join(my_input_path, input_file.filename))
        if output_file and allowed_file(output_file.filename):
            my_output_path = os.path.join(join_path, "output")
            if not os.path.exists(my_output_path):
                os.makedirs(my_output_path)
            output_file.save(os.path.join(my_output_path, output_file.filename))
        input_path = str(os.path.join(os.path.abspath(my_input_path), input_file.filename))
        output_path = str(os.path.join(os.path.abspath(my_output_path), output_file.filename))
        test_point = QuestionTestPoint(0,
                                       get_file_num(input_file.filename),
                                       question_id,
                                       input_path,
                                       output_path,
                                       score)
        test_point_list.append(test_point)
    try:
        db.session.add_all(test_point_list)
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    return response(200, "Add Program Success", {"questionID": question_id})
    # return response(200, "Add Program Success", {})


@question_blueprint.route("/search_list", methods=["POST"])
def question_search_list():
    """
    根据条件搜索 question
    :return:
    """
    data = get_data()
    try:
        current_page = int(request.args.get("currentPage"))
    except:
        current_page = 1
    data_per_page = 10
    course_id = data.get("courseId")
    question_title = data.get("questionTitle")
    question_type = data.get("questionType")
    question_id = data.get("questionId")
    sql = "SELECT * FROM `{}` WHERE"
    question_types = [
        "question_of_fill_blank",
        "question_of_select",
        "question_of_judge",
        "question_of_program_fill_blank",
        "question_of_program_modify",
        "question_of_program"
    ]
    r = list()

    if question_id is None and question_title is None and course_id is None:
        sql = "SELECT * FROM `{}`"
    if question_id:
        tmp = dict()
        tmp_question = Question.query.filter_by(question_id=question_id).first()
        if tmp_question is None:
            raise APIException(NO_QUESTION_EXISTS)
        real_question, question_type = get_real_question(question_type)

        sql = "SELECT count(*) FROM `user_submit` WHERE status=TRUE AND question_id=" + str(question_id)
        right_submits = db.session.execute(sql).scalar()
        sql = "SELECT count(*) FROM `user_submit` WHERE status=TRUE AND result=100 AND question_id=" + str(question_id)
        all_submits = db.session.execute(sql).scalar()
        tmp["problemId"] = real_question.question_id
        tmp["problemTitle"] = real_question.question_title
        tmp["problemDifficulty"] = real_question.question_difficulty
        tmp["questionCreateTime"] = str(real_question.create_time)
        tmp["questionType"] = get_type(question_type)

        if all_submits != 0:
            tmp["passPercent"] = right_submits / all_submits
        else:
            tmp["passPercent"] = 0
        r.append(tmp)

        list_len = 1
        max_page_num = ceil(list_len / data_per_page)

        ret = {
            "currentPage": current_page,
            "maxPageNum": max_page_num,
            "num": list_len,
            "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
        }
        return response(200, "Query Question List Success", ret)

    if course_id:
        sql += " `relate_course_id`=" + str(course_id) + " AND"
    if question_title:
        sql += " `question_title` LIKE '%{}%'".format(question_title) + " AND"
    if question_type:
        if question_type == 1:
            question_types = ["question_of_fill_blank"]
        if question_type == 2:
            question_types = ["question_of_select"]
        if question_type == 3:
            question_types = ["question_of_judge"]
        if question_type == 4:
            question_types = ["question_of_program_fill_blank"]
        if question_type == 5:
            question_types = ["question_of_program_modify"]
        if question_type == 6:
            question_types = ["question_of_program"]

    for q_type in question_types:
        questions = db.session.execute(sql.format(q_type)[: -4])
        questions = list(questions)
        questions.sort(key=lambda x: x.create_time)
        if questions == []:
            continue
        for question in questions:
            tmp = dict()
            question_id = question.question_id
            right_sql = "SELECT count(*) FROM `user_submit` WHERE status=TRUE AND question_id=" + str(question_id)
            right_submits = db.session.execute(right_sql).scalar()
            count_sql = "SELECT count(*) FROM `user_submit` WHERE status=TRUE AND result=1 AND question_id=" + str(question_id)
            all_submits = db.session.execute(count_sql).scalar()
            tmp["problemId"] = question.question_id
            tmp["problemTitle"] = question.question_title
            tmp["problemDifficulty"] = question.question_difficulty
            tmp["questionCreateTime"] = str(question.create_time)

            if q_type == "question_of_fill_blank":
                return_question_type = "填空题"
            elif q_type == "question_of_select":
                return_question_type = "选择题"
            elif q_type == "question_of_judge":
                return_question_type = "判断题"
            elif q_type == "question_of_program_fill_blank":
                return_question_type = "程序填空题"
            elif q_type == "question_of_program_modify":
                return_question_type = "程序改错题"
            elif q_type == "question_of_program":
                return_question_type = "编程题"
            else:
                return_question_type = "WRONG TYPE"
            tmp["questionType"] = return_question_type

            if all_submits != 0:
                tmp["passPercent"] = right_submits / all_submits
            else:
                tmp["passPercent"] = 0
            r.append(tmp)

    list_len = len(r)
    max_page_num = ceil(list_len / data_per_page)
    ret = {
        "currentPage": current_page,
        "maxPageNum": max_page_num,
        "num": list_len,
        "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
    }

    return response(200, "Search Question Success", ret)


@question_blueprint.route("/submit/list", methods=["GET", "POST"])
def question_submits():
    """
    所有提交信息
    :return:
    """
    try:
        current_page = int(request.args.get("currentPage"))
    except:
        current_page = 1
    data_per_page = 10
    user_submits = UserSubmit.query.filter_by(status=True).order_by(-UserSubmit.create_time).all()
    if not user_submits:
        raise APIException(NO_USER_SUBMITS_EXISTS)
    r = list()

    for user_submit in user_submits:
        user = User.query.filter_by(username=user_submit.user_id).first()
        if user is None:
            continue
        tmp = dict()
        tmp["submit_id"] = user_submit.submit_id
        tmp["nickname"] = user.nickname if user.nickname else str(user.username)
        tmp["question_id"] = user_submit.question_id
        tmp["language"] = num2language(user_submit.language)
        tmp["result"] = get_code_status(user_submit.result)
        tmp["code_status"] = get_code_status(user_submit.code_status)
        r.append(tmp)

    list_len = len(r)
    max_page_num = ceil(list_len / data_per_page)

    ret = {
        "currentPage": current_page,
        "maxPageNum": max_page_num,
        "num": list_len,
        "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
    }
    return response(200, "Query User Submit List Success", ret)


@question_blueprint.route("/submit", methods=["POST"])
@user_is_login
def answer_submit():
    """
    用户答题
    :return:
    """
    # TODO 前端输入格式
    data = get_data()
    question_id = data.get("questionId")
    user_answers = data.get("userAnswer")
    language = data.get("language")
    username = session.get("username")

    question = Question.query.filter_by(question_id=question_id).first()
    if question is None:
        raise APIException(NO_QUESTION_EXISTS)
    question_type = question.question_type

    # 填空题
    if question_type == 1:
        question = QuestionOfFillBlank.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        user_submit = UserSubmit(int(username), question_id, language)
    # 选择题
    elif question_type == 2:
        question = QuestionOfSelect.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        user_submit = UserSubmit(int(username), question_id, language)
    # 判断题
    elif question_type == 3:
        question = QuestionOfJudge.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        user_submit = UserSubmit(int(username), question_id, language)
        user_submit.user_answer = user_answers
    # 程序填空题
    elif question_type == 4:
        question = QuestionOfProgramFillBlank.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        user_submit = UserSubmit(int(username), question_id, language)
    # 程序改错题
    elif question_type == 5:
        question = QuestionOfProgramModify.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        user_submit = UserSubmit(int(username), question_id, language)
    # 编程题
    elif question_type == 6:
        question = QuestionOfProgram.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        user_submit = UserSubmit(int(username), question_id, language)
        user_submit.source_code = user_answers

    # 保存 user_submit 到数据库中
    try:
        db.session.add(user_submit)
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)

    # 发送消息到 OJ
    user_submit_id = user_submit.submit_id
    get_params = {"submitId": user_submit.submit_id}
    res = requests.get(oj_url+"judge", get_params)

    return response(200, "User Submit Success", {"res": res.text})


@question_blueprint.route("/delete", methods=["POST"])
@user_is_login
@check_user_type_2
def question_delete():
    """
    删除问题
    :return:
    """
    data = get_data()
    question_id = data.get("questionId")
    question = Question.query.filter_by(question_id=question_id).first()
    if question is None:
        raise APIException(NO_QUESTION_EXISTS)
    question_type = question.question_type
    res = Question.query.filter_by(question_id=question_id).delete()
    if question_type == 1:
        exact_res = QuestionOfFillBlank.query.filter_by(question_id=question_id).delete()
    elif question_type == 2:
        exact_res = QuestionOfSelect.query.filter_by(question_id=question_id).delete()
    elif question_type == 3:
        exact_res = QuestionOfJudge.query.filter_by(question_id=question_id).delete()
    elif question_type == 4:
        exact_res = QuestionOfProgramFillBlank.query.filter_by(question_id=question_id).delete()
    elif question_type == 5:
        exact_res = QuestionOfProgramModify.query.filter_by(question_id=question_id).delete()
    elif question_type == 6:
        exact_res = QuestionOfProgram.query.filter_by(question_id=question_id).delete()
    try:
        db.session.commit()
        db.session.close()
    except:
        db.session.rollback()
        raise APIException(DELETE_ERROR)

    return response(200, "Delete Question Success", {"questionId": question_id})


@question_blueprint.route("/submit/search", methods=["POST"])
def submit_search():
    """
    根据条件查询 问题列表
    :return:
    """
    data = get_data()
    search_user = data.get("searchUser")
    question_id = data.get("questionId")
    language = data.get("language")
    result = data.get("result")
    sql = "SELECT * FROM `user_submit` WHERE"
    try:
        current_page = int(request.args.get("currentPage"))
    except:
        current_page = 1
    data_per_page = 10
    if search_user is None and question_id is None and language is None and result is None:
        user_submits = UserSubmit.query.filter_by(status=True).order_by(-UserSubmit.create_time).all()
    else:
        if search_user:
            sql += " `user_id`={}".format(search_user) + " AND"
        if question_id:
            sql += " `question_id`={}".format(question_id) + " AND"
        if language:
            sql += " `language`={}".format(get_language(language)) + " AND"
        if result:
            sql += " `result`={}".format(result) + " AND"
        user_submits = db.session.execute(sql[: -4])
    if not user_submits:
        raise APIException(NO_USER_SUBMITS_EXISTS)
    r = list()

    user_submits = list(user_submits)
    list_len = len(user_submits)
    for user_submit in user_submits:
        tmp = dict()
        tmp["submit_id"] = user_submit.submit_id
        user = User.query.filter_by(username=user_submit.user_id).first()
        if user is None:
            continue
        tmp["nickname"] = user.nickname if user.nickname else str(user.username)
        tmp["question_id"] = user_submit.question_id
        tmp["language"] = num2language(user_submit.language)
        tmp["result"] = get_code_status(user_submit.result)
        r.append(tmp)

    max_page_num = ceil(list_len / data_per_page)

    ret = {
        "currentPage": current_page,
        "maxPageNum": max_page_num,
        "num": list_len,
        "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
    }
    return response(200, "Query User Submit List Success", ret)


@question_blueprint.route("upload", methods=["POST"])
@user_is_login
@check_user_type_2
def upload_test_file():
    data = get_data()
    input_files = request.files.getlist("inputFile")
    output_files = request.files.getlist("outputFile")
    question_id = data.get("questionId")
    username = session.get("username")
    score = data.get("score")

    test_point_list = list()
    for input_file, output_file in zip(input_files, output_files):
        if input_file and allowed_file(input_file.filename):
            join_path = os.path.join(TARGET_PATH, str(username), get_file_num(input_file.filename))
            my_input_path = os.path.join(join_path, "input")
            if not os.path.exists(my_input_path):
                os.makedirs(my_input_path)
            input_file.save(os.path.join(my_input_path, input_file.filename))
        if output_file and allowed_file(output_file.filename):
            my_output_path = os.path.join(join_path, "output")
            if not os.path.exists(my_output_path):
                os.makedirs(my_output_path)
            output_file.save(os.path.join(my_output_path, output_file.filename))
        input_path = str(os.path.join(os.path.abspath(my_input_path), input_file.filename))
        output_path = str(os.path.join(os.path.abspath(my_output_path), output_file.filename))
        test_point = QuestionTestPoint(0,
                                       get_file_num(input_file.filename),
                                       question_id,
                                       input_path,
                                       output_path,
                                       score)
        test_point_list.append(test_point)
    try:
        db.session.add_all(test_point_list)
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    res = requests.get(oj_url+"updateQuestion", params={"questionId": question_id})

    return response(200, "Add Test Point File Success", {"questionId": question_id, "res": res.text})
